#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <iostream>

#include "heads.h"

#define _MAX_HOST_LENGTH_ 100

using namespace std;

void color(int couleurDuTexte,int couleurDeFond)
{
    HANDLE H=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(H,couleurDeFond*16+couleurDuTexte);
}

serveur::serveur(int p){
	port	= p;
	running	= false;
}

int serveur::init(){
	struct in_addr  MyAddress;
	struct hostent  *host;
	char HostName[_MAX_HOST_LENGTH_];
	WSADATA	      wsaData;

	if(WSAStartup(MAKEWORD(2,2), &wsaData ) != 0 ){
		cerr <<"WSAStartup a echoue "<< endl;
		return 1;
	}

	if( gethostname( HostName, _MAX_HOST_LENGTH_ ) == SOCKET_ERROR ){
		cerr<< "gethostname() a rencontre l'erreur "<< WSAGetLastError()  << endl;
		return 1;
	}

	if( (host = gethostbyname( HostName ) ) == NULL){
		cerr <<"gethostbyname() a rencontre l'erreur "<< WSAGetLastError()<< endl;
		return 1;
	}

	memcpy( &MyAddress.s_addr, host->h_addr_list[0], sizeof( MyAddress.s_addr ) );

	ServerAddr.sin_family = AF_INET;
	ServerAddr.sin_port = htons( port );
	ServerAddr.sin_addr.s_addr = inet_addr(inet_ntoa(MyAddress));

	cout <<"server correctement initialise" << endl;
	return 0;
}

int serveur::start (){
	SOCKADDR_IN                 ClientAddr;
	int                         ClientAddrLen;
	HANDLE                      hProcessThread;
	SOCKET                      NewConnection;
	struct thread_param         p;

	if( ( ListeningSocket = socket( PF_INET, SOCK_STREAM, IPPROTO_TCP ) ) == INVALID_SOCKET ){
		cerr << "ne peut creer la socket. Erreur n " << WSAGetLastError()<< endl;
		WSACleanup();
		return 1;
	}

	if( bind( ListeningSocket, (SOCKADDR *)&ServerAddr, sizeof( ServerAddr ) ) == SOCKET_ERROR ){
		cerr << "bind a echoue avec l'erreur " << WSAGetLastError() << endl;
		cerr << "Le port est peut-etre deja utilise par un autre processus " << endl;
		closesocket( ListeningSocket );
		WSACleanup();
		return 1;
	}

	if( listen( ListeningSocket, 5 ) == SOCKET_ERROR ){
		cerr << "listen a echoue avec l'erreur " << WSAGetLastError() << endl;
		closesocket( ListeningSocket );
		WSACleanup();
		return 1;
	}

	cout << "serveur demarre : a l'ecoute du port " << port << endl;
	running = true;
	ClientAddrLen = sizeof( ClientAddr );

	while(running)
	{

        if((NewConnection = accept( ListeningSocket, (SOCKADDR *) &ClientAddr, &ClientAddrLen)) == INVALID_SOCKET)
        {
            cerr  << "accept a echoue avec l'erreur " << WSAGetLastError() << endl;;
            closesocket( ListeningSocket );
            WSACleanup();
            return 1;
        }

        p.ser = this;
        p.soc = NewConnection;

        color(6, 0);
        cout << "client connecte ::  IP : " <<inet_ntoa( ClientAddr.sin_addr )<< " ,port = " <<ntohs( ClientAddr.sin_port ) << endl;

        hProcessThread = CreateThread(NULL, 0,&serveur::ThreadLauncher, &p,0,NULL);
        if ( hProcessThread == NULL )
        {
            cerr << "CreateThread a echoue avec l'erreur " <<GetLastError()<< endl;
        }

	}

	return 0;
}

int serveur::pause (){
	running = false;
	cout << "Serveur en pause" << endl;
	closesocket( ListeningSocket );
	return 0;
}

/* ======================================================================== */
/* ========================== thread proc ================================= */
/* ======================================================================== */


DWORD serveur::ClientThread(SOCKET soc){
    color(6, 0);
	cout << "thread client demarre" << endl;

    char bufs[100] = "Connexion OK.\n";
    char recu[255] = "";
    char envoi [255] = "", rien[1] = {'\0'};
    long size = 0, lentgh = 0;
    bool ThreadRunning = true;

    //msg de bienvenu
    send(soc, bufs, sizeof(bufs), 0);


    while(ThreadRunning)
    {
        size = recv(soc, recu, sizeof(recu), 0);
        if(size > 1)
        {

            color(2, 0);
            printf("%s (%ld chars)\n",recu, strlen(recu));
            send(soc, recu, sizeof(recu), 0);

            strcpy(recu, rien);
        }
        size = 0;
    }

	return 0;
}
